package engine

import (
	"context"
	"gitee.com/gitee-go/core"
	"gitee.com/gitee-go/server/engine/comm"
	"gitee.com/gitee-go/server/engine/local"
	"gitee.com/gitee-go/utils/ioex"
	"github.com/sirupsen/logrus"
	"os"
	"os/signal"
	"runtime/debug"
	"time"
)

type Manager struct {
	Ctx  context.Context
	cncl context.CancelFunc

	buildEngine    comm.IBuildEngine
	preBuildEngine comm.IPreBuildEngine

	clientEngine *local.ClientEngine
	refreshEgn   *local.RefreshEngine
}

var (
	mgr  *Manager
	csig chan os.Signal
)

func init() {
	mgr = &Manager{}
	csig = make(chan os.Signal, 1)
	mgr.Ctx, mgr.cncl = context.WithCancel(context.Background())
}
func Mgr() *Manager {
	return mgr
}
func Wait() {
	for !ioex.CheckContext(mgr.Ctx) {
		if mgr == nil || mgr.cncl == nil {
			break
		}
		time.Sleep(time.Millisecond * 10)
	}
	logrus.Info("engine mgr end!!!!")
}
func Stop() {
	logrus.Info("engine mgr stop!!!!")
	if mgr != nil && mgr.cncl != nil {
		mgr.cncl()
		mgr.cncl = nil
	}
}

// 启动所有engine
func Start() error {
	signal.Notify(csig, os.Interrupt, os.Kill)
	go func() {
		s := <-csig
		logrus.Infof("get signal(%d):%s", s, s.String())
		Stop()
	}()
	go mgr.init()

	// runner 注册引擎
	mgr.clientEngine = local.StartClientEngine(mgr.Ctx)
	// 任务调度引擎
	mgr.buildEngine = local.StartBuildEngine(mgr.Ctx, mgr.clientEngine)
	// webhook,git clone,yaml解析 引擎
	mgr.preBuildEngine = local.StartPreBuildEngine(mgr.Ctx, mgr.buildEngine, mgr.clientEngine)

	// user oauth token ,仓库 刷新引擎
	mgr.refreshEgn = local.StartRefreshEngine(mgr.Ctx)
	return nil
}
func (c *Manager) init() {
	defer func() {
		if err := recover(); err != nil {
			core.LogPnc.Errorf("Manager init:%+v", err)
			core.LogPnc.Errorf("%s", string(debug.Stack()))
		}
	}()

	c.initPlugs()
}

// -----------------getters

func (c *Manager) GetBuildEgn() comm.IBuildEngine {
	return c.buildEngine
}
func (c *Manager) GetPreBuildEgn() comm.IPreBuildEngine {
	return c.preBuildEngine
}
func (c *Manager) GetClientEgn() *local.ClientEngine {
	return c.clientEngine
}
func (c *Manager) GetRefreshEgn() *local.RefreshEngine {
	return c.refreshEgn
}
